/**  
 * Copyrights@2006, Tianyuan DIC Information Co.,Ltd.
 * 文件名:    TMallPayHandle.java  
 * 描述:   
 * 作者:     kaiyang
 * 版本:    1.0  
 * 创建时间:   2015年5月4日 上午11:57:29  
 *  
 * 修改历史:  
 * 日期                          作者           版本         描述  
 * ------------------------------------------------------------------  
 * 2015年5月4日      kaiyang      1.0        1.0 Version  
 */ 
package com.hp.bon.sgw.wh.channel.handler;

import java.io.PrintStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.stream.XMLInputFactory;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.hp.bon.sgw.Constants;
import com.hp.bon.sgw.Constants.MessageType;
import com.hp.bon.sgw.bean.XmlMessage;
import com.hp.bon.sgw.core.BuzProcessorManager;
import com.hp.bon.sgw.core.CallParam;
import com.hp.bon.sgw.core.channel.SoapChannel;
import com.hp.bon.sgw.core.channel.handler.IAsynCallHandler;
import com.hp.bon.sgw.domain.MessageDetail;
import com.hp.bon.sgw.start.SpringContext;
import com.hp.bon.sgw.threads.MessageDetailCacheManager;
import com.hp.bon.sgw.threads.TaskManager;
import com.hp.bon.sgw.wh.bean.Result;
import com.hp.bon.sgw.wh.service.TMallResponseService;
import com.hp.bon.sgw.wh.service.TmallLogDao;
import com.hp.bon.sgw.wh.util.DateUtil;
import com.hp.ocs.diameter.message.AVP;
import com.hp.ocs.diameter.message.AVP_Grouped;
import com.hp.ocs.diameter.message.AVP_Integer32;
import com.hp.ocs.diameter.message.AVP_Integer64;
import com.hp.ocs.diameter.message.Message;

/**  
 * @ClassName: TMallPayHandle   
 * @author: wanghan  
 * @date:2017年2月16日 上午11:57:29     
 */
public class NetListQueryHandler implements IAsynCallHandler{

	private static final Logger _log = LoggerFactory.getLogger(TaobaoFeeHandle.class);
	private PrintStream printStream;
	private Map<String, Object> data =new HashMap<String, Object>();
	private TMallResponseService tmallResponseService;
	private ThreadPoolTaskExecutor asynExecutor;
	TmallLogDao tmallLogDao=(TmallLogDao)SpringContext.getInstance().getApplicationContext().getBean("tmallLogDao");
	private String url;
	static XMLInputFactory inputFactory = XMLInputFactory.newInstance();
	private static Map<String, String> areacode =new HashMap<String, String>();
	private static Map<String, String> qhmap =new HashMap<String, String>();
	
	static{
		areacode.put("0271001","1001");
		areacode.put("07101003","1003");
		areacode.put("07131004","1004");
		areacode.put("07171005","1005");
		areacode.put("07121006","1006");
		areacode.put("07121007","1007");
		areacode.put("07151008","1008");
		areacode.put("07191009","1009");
		areacode.put("07241010","1010");
		areacode.put("07141011","1011");
		areacode.put("07221012","1012");
		areacode.put("07181013","1013");
		areacode.put("07281014","1014");
		areacode.put("07281015","1015");
		areacode.put("07281016","1016");
		areacode.put("07191017","1017");
		areacode.put("07161018","1018");
		
		qhmap.put("027","1");
		qhmap.put("0710","1");
		qhmap.put("0713","1");
		qhmap.put("0717","1");
		qhmap.put("0712","1");
		qhmap.put("0712","1");
		qhmap.put("0715","1");
		qhmap.put("0719","1");
		qhmap.put("0724","1");
		qhmap.put("0714","1");
		qhmap.put("0722","1");
		qhmap.put("0718","1");
		qhmap.put("0728","1");
		qhmap.put("0719","1");
		qhmap.put("0716","1");
	}
	public NetListQueryHandler(PrintStream printStream, Map<String, Object> data,
			TMallResponseService tmallResponseService,
			ThreadPoolTaskExecutor asynExecutor, String url) {
		this.printStream = printStream;
        this.tmallResponseService = tmallResponseService;
        this.asynExecutor = asynExecutor;
        this.url = url;
        this.data = data;
	}

	@Override
	public int getProtocolType() {
		
		return 0;
	}
  
	@Override
	public void onCallResult(CallParam callParam) {
		XmlMessage ack = null;
		Object response = null;
		if (callParam.getResponse() != null) {
			response = callParam.getResponse();
		} else if (callParam.getRecvResponse() != null) {
			response = callParam.getRecvResponse();
		}
		if (response == null) {
			ack = SoapChannel.createERRAnwser(
					callParam.getSessionId(),
					callParam.getRetCode() == 3002 ? 11202 : callParam
							.getRetCode(), callParam.getResultMsg());
		} else {
			if (response instanceof Message) {// CCA -> XML
				ack = BuzProcessorManager.getInstance().convertMessageToAck(
						callParam);
			} else if (response instanceof XmlMessage) {
				ack = (XmlMessage) response;
			} else {
				_log.warn("unknown response type:"
						+ callParam.getResponse().getClass().getName());
			}
		}
		try {
			
			_log.info("CCA 返回信息");
			String serviceCode = data.get("ServiceCode").toString();
			String respXML = convertResponseString((Message)response,callParam.getServiceResultCode());
			
			byte[] resp = respXML.getBytes("utf-8");
			ack.setLength(resp.length);
			ack.setMsgTime(System.currentTimeMillis());
			printStream.write(resp);
			printStream.close();
            if(!"SVC81011".equals(serviceCode)) {
            	callParam.setRetCode(-1);
            }
			callParam.setResponse(ack);

			if (callParam.getRetCode() == Constants.ResultCode.SUCCESS) {// 成功的消息，请求应答入库

				MessageDetail detail = new MessageDetail();
				detail.setBusinessCallId(callParam.getBussinessCallId());
				detail.setSessionId(callParam.getSessionId());
				detail.setServiceContextId(callParam.getServiceContextId());
				detail.setMessageType(MessageType.WSA);
				detail.setDetails(ack.getDATA());
				detail.setMsgTime(new Date(ack.getMsgTime()));
				detail.setOpType("send");
				detail.setHostId(callParam.getUserName());
				MessageDetailCacheManager.getInstance().add(detail);
			}
			TaskManager.taskProcess(callParam);
		} catch (Exception e) {
			try {
				String respStr =  returnXml(data.get("TransactionID").toString(), "1002", "接口服务器异常");
				byte[] resp = respStr.getBytes("utf-8");
				ack.setLength(resp.length);
				ack.setMsgTime(System.currentTimeMillis());
				printStream.write(resp);
				printStream.close();
			} catch (Exception e1) {
				_log.info("异常详情:"+e1);
			}
    		_log.info("异常详情:"+e);
			e.printStackTrace();
		}
	}


	private String convertResponseString(Message answer, int serviceResultCode) throws Exception
	{
		String response = "";	
		String serviceCode = data.get("ServiceCode").toString();
		if(!"SVC81011".equals(serviceCode)) {
			return returnXml(data.get("TransactionID").toString(), "1007", "不支持的查询类型");
		} else {
			if (serviceResultCode == 0)   //充值成功
			{
				AVP avp = answer.find(Constants.DIAMETER_AVP_SERVICE_INFOMATION,Constants.DIAMETER_VENDOR_3GPP);
			    AVP_Grouped avpServiceInfomation = new AVP_Grouped(avp);
			    
			    AVP Data_InformationAvp = avpServiceInfomation.find(80400,Constants.DIAMETER_VENDOR_CT);
			    AVP_Grouped avpData_Information = new AVP_Grouped(Data_InformationAvp);
			    
			    //Bill_Serial_Nbr
			    long serv_id =0L;
			    AVP servIdAvp = avpData_Information.find(90020,Constants.DIAMETER_VENDOR_CT);
			    if (servIdAvp != null){
			    	serv_id =new AVP_Integer64(servIdAvp).queryValue();
			    }
			    _log.info("serv_id："+serv_id);
			    
			    
			    int homeAreaCode =0;
			    AVP homeAreaCodeAvp = avpData_Information.find(80615,Constants.DIAMETER_VENDOR_CT);
			    if (homeAreaCodeAvp != null){
			    	homeAreaCode =new AVP_Integer32(homeAreaCodeAvp).queryValue();
			    }
			    
			    _log.info("homeAreaCode："+homeAreaCode);
			    int paymentFlag =0;
			    AVP paymentFlagAvp = avpData_Information.find(82023,Constants.DIAMETER_VENDOR_CT);
			    if (paymentFlagAvp != null){
			    	paymentFlag =new AVP_Integer32(paymentFlagAvp).queryValue();
			    }
			    _log.info("paymentFlag："+paymentFlag);
				
				StringBuffer para = new StringBuffer();
				para.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.hquery.ailk.com/\">");
				para.append("<soapenv:Header/>");
				para.append("<soapenv:Body>");
				para.append("<ws:hquery>");
				para.append("<param>");
				para.append("<![CDATA[  ");
				String type =data.get("QueryType").toString();
				
				if("1".equals(type)){
					para.append("<query type='14' from='212'>");
				}else if("2".equals(type)){
					if(paymentFlag==1){
						para.append("<query type='8' from='212'>");
					}else{
						para.append("<query type='15' from='212'>");
					}
					
				}else if("3".equals(type)||"4".equals(type)){
					para.append("<query type='13' from='212'>");
				}
				
				para.append("<param name='acctId'></param>");
				para.append("<param name='servid'>"+serv_id+"</param>");
				para.append("<param name='selectType'>0</param>");
				para.append("<param name='beginDate'>"+data.get("StartTime").toString()+"000000</param>");
				para.append("<param name='endDate'>"+data.get("EndTime").toString()+"235959</param>");
				para.append("<param name='getFlag'>0</param>");
				para.append("<param name='areaCode'>"+homeAreaCode+"</param>");
				para.append("<start name='queryBatchStart'></start>");
				para.append("<start name='queryBatch'></start>");
				para.append("</query>");
				para.append("]]>");
				para.append("</param>");
				para.append("</ws:hquery>");
				para.append("</soapenv:Body>");
				para.append("</soapenv:Envelope>");
				
				PostMethod post = new PostMethod(url);
				RequestEntity requestEntity = new StringRequestEntity(para.toString(), "text/xml", "UTF-8");
				post.setRequestEntity(requestEntity);
				HttpClient client = new HttpClient();
				client.getHttpConnectionManager().getParams().setConnectionTimeout(10*1000);
				client.executeMethod(post);
				String resp = post.getResponseBodyAsString();
				
				
				if(resp!=null&&!"".equals(resp)){
					Result result =soapToResult(resp);
					if(result.isSuccess()){
						StringBuffer sb =new StringBuffer();
						sb.append("<?xml version='1.0' encoding='UTF-8'?>");
						sb.append("<ContractRoot>");
						sb.append("<TcpCont>");
						sb.append("<ActionCode>1</ActionCode>");
						sb.append("<TransactionID>"+data.get("TransactionID").toString()+"</TransactionID>");
						sb.append("<RspTime>"+DateUtil.dateTimeToStr(new Date())+"</RspTime>");
						sb.append("<Response>");
						sb.append("<RspType>0</RspType>");
						sb.append("<RspCode>0000</RspCode>");
						sb.append("<RspDesc>成功</RspDesc>");
						sb.append("</Response>");
						sb.append("</TcpCont>");
						sb.append("<SvcCont>");
						sb.append("<QryInfoRsp>");
						sb.append("<InfoTypeID>21</InfoTypeID> ");
						String str[]=null;
						if("1".equals(type)){
							String areaName ="";
							for (int i = 0; i < result.getResult().size(); i++) {
								str=result.getResult().get(i).split(",", -1);
								sb.append("<CallDetail>");
								sb.append("<CallType>"+str[4]+"</CallType>");
								sb.append("<CallMobile>"+str[0]+"</CallMobile>");
								sb.append("<CallTime>"+DateUtil.dateTimeToStr(DateUtil.dateTimeToDate(str[2]))+"</CallTime>");
								sb.append("<CallTimeCost>"+DateUtil.secToTime(Integer.valueOf(str[3]))+"</CallTimeCost>");
								sb.append("<CallFee>"+(Integer.valueOf(changeY2F(str[10]))+Integer.valueOf(changeY2F(str[12]))+Integer.valueOf(changeY2F(str[14])))+"</CallFee>");
								areaName =tmallLogDao.getAreaName(str[7]);
								if(areaName==null||"".equals(areaName)){
									sb.append("<CallArea></CallArea>");
								}else{
									sb.append("<CallArea>"+areaName+"</CallArea>");
								}
								
								
								//2. 通过QH(0728)+HomeAreaCode(1011)去匹配17个地市的区号+本地网编码，如果有记录，则为本地，填3；
								if(areacode.get(str[7]+homeAreaCode)!=null){
									sb.append("<CallStyle>0</CallStyle>");
								}else{
									sb.append("<CallStyle>2</CallStyle>");
								}
								sb.append("</CallDetail>");
							}
						}else if("2".equals(type)){
							for (int i = 0; i < result.getResult().size(); i++) {
								str=result.getResult().get(i).split(",", -1);
								sb.append("<SmsDetail>");
								sb.append("<SmsType>0</SmsType>");
								sb.append("<SmsStyle>0</SmsStyle>");
								if(str[0].startsWith("00")){
									sb.append("<SmsArea>1</SmsArea>");
								}else{
									sb.append("<SmsArea>0</SmsArea>");
								}
								sb.append("<SmsMobile>"+str[0]+"</SmsMobile>");
								sb.append("<SmsTime>"+DateUtil.dateTimeToStr(DateUtil.dateTimeToDate(str[1]))+"</SmsTime>");
								if(paymentFlag==0){
									sb.append("<SmsCost>"+Integer.valueOf(changeY2F(str[4]))+"</SmsCost>");
								}else if(paymentFlag==1){
									sb.append("<SmsCost>"+Integer.valueOf(changeY2F(str[3]))+"</SmsCost>");
								}
								sb.append("</SmsDetail>");
							}
						}else if("3".equals(type)||"4".equals(type)){
							Integer qh =null;
							for (int i = 0; i < result.getResult().size(); i++) {
								str=result.getResult().get(i).split(",", -1);
								sb.append("<NetDetail>");
								sb.append("<NetType>"+str[3]+"</NetType>");
								double netFlow = 0.0;
								int  netFlowInt = 0;
								double v = 0.0;
								try {
									netFlow = Double.parseDouble(str[2]);
									v = new BigDecimal(netFlow).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
									netFlowInt = (int) v; 
								} catch (Exception e) {
									netFlowInt = 0;
								}
								sb.append("<NetFlow>"+netFlowInt+"</NetFlow>");
								String netTimeStr = "";
								String netTimeCostStr = "";
								int netFee = 0;
								try {
									netTimeStr = DateUtil.dateTimeToStr(DateUtil.dateTimeToDate(str[0]));
								} catch (Exception e) {
									netTimeStr = "";
								}
								try {
									netTimeCostStr = DateUtil.secToTime(Integer.valueOf(str[1]));
								} catch (Exception e) {
									netTimeCostStr = "";
								}
								try {
									netFee = Integer.valueOf(changeY2F(str[6]));
								} catch (Exception e) {
									netFee = 0;
								}
								sb.append("<NetTime>"+(netTimeStr.equals("") ? "00:00:00" :netTimeStr)+"</NetTime>");
								sb.append("<NetTimeCost>"+(netTimeCostStr.equals("") ? "00:00:00" :netTimeCostStr)+"</NetTimeCost>");
								sb.append("<NetFee>"+netFee+"</NetFee>");
								sb.append("<NetArea>"+str[4]+"</NetArea>");
								qh =tmallLogDao.getQH(str[4]);
								if(areacode.get(qh+homeAreaCode)!=null){
									sb.append("<NetStyle>3</NetStyle>");
								}else if (qhmap.get(qh)!=null){
									sb.append("<NetStyle>2</NetStyle>");
								}else if (qh.toString().startsWith("00")){
									sb.append("<NetStyle>4</NetStyle>");
								}else{
									sb.append("<NetStyle>1</NetStyle>");
								}
								
								sb.append("<NetBusiness>"+str[5]+"</NetBusiness>");
								sb.append("</NetDetail>");
							}
						}
						sb.append("</QryInfoRsp>");
						sb.append("</SvcCont>");
						sb.append("</ContractRoot>");
						response=sb.toString();
					}else{
						_log.info("========result.isSuccess()========false" );
						return returnXml(data.get("TransactionID").toString(), "1002", "接口服务器异常");
					}
				}else{
					
					return returnXml(data.get("TransactionID").toString(), "1001", "接口调用超时");
				}
			}else   //查询失败
			{
				return returnXml(data.get("TransactionID").toString(), "1005", "缺失账户信息");
			}
		}
		return response;
	}
	
	/**
	 * 返回报文
	 */
	
	public static String returnXml(String TransactionID,String RspCode,String RspDesc){
		StringBuffer sb =new StringBuffer();
		sb.append("<?xml version='1.0' encoding='UTF-8'?>");
		sb.append("<ContractRoot>");
		sb.append("<TcpCont>");
		sb.append("<ActionCode>1</ActionCode>");
		sb.append("<TransactionID>"+TransactionID+"</TransactionID>");
		sb.append("<RspTime>"+DateUtil.dateTimeToStr(new Date())+"</RspTime>");
		sb.append("<Response>");
		sb.append("<RspType>1</RspType>");
		sb.append("<RspCode>"+RspCode+"</RspCode>");
		sb.append("<RspDesc>"+RspDesc+"</RspDesc>");
		sb.append("</Response>");
		sb.append("</TcpCont>");
		sb.append("</ContractRoot>");
		return sb.toString();
	}
	/** 
     * 将xml格式的字符串转换成Map对象 
     *  
     * @param xmlStr xml格式的字符串 
     * @return Map对象 
     * @throws Exception 异常 
     */  
    public static Result soapToResult(String xmlStr) throws Exception {  
    	
    	_log.info("SoapToResult is start");
    	Result map =new Result(); 
        //将xml格式的字符串转换成Document对象  
        Document doc = DocumentHelper.parseText(xmlStr);  
        //获取根节点  
        Element root = doc.getRootElement();  
        //获取根节点下的所有元素  
        List children = root.elements();  
        
        List<String> result =new ArrayList<String>();
        //循环所有子元素  
        if(children != null && children.size() > 0) {  
            for(int i = 0; i < children.size(); i++) {  
                Element child = (Element)children.get(i);  
                	for(int j = 0; j < child.elements().size(); j++) { 
                		Element child1 = (Element)child.elements().get(j);  
                		for (int k = 0; k < child1.elements().size(); k++) {
                			Element child2 = (Element)child1.elements().get(k);  
							if("return".equals(child2.getName())){
								for (int l = 0; l <child2.elements().size(); l++) {
									Element child3 = (Element)child2.elements().get(l);
			                		if("curStartInfo".equals(child3.getName())){
			                			map.setCurStartInfo(child3.getTextTrim());
			                		}else if("dur1".equals(child3.getName())){
			                			map.setDur1(child3.getTextTrim());
			                		}else if("dur2".equals(child3.getName())){
			                			map.setDur2(child3.getTextTrim());
			                		}else if("dur3".equals(child3.getName())){
			                			map.setDur3(child3.getTextTrim());
			                		}else if("existNext".equals(child3.getName())){
			                			map.setExistNext(Boolean.valueOf(child3.getTextTrim()));
			                		}else if("fee1".equals(child3.getName())){
			                			map.setFee1(child3.getTextTrim());
			                		}else if("fee2".equals(child3.getName())){
			                			map.setFee2(child3.getTextTrim());
			                		}else if("fee3".equals(child3.getName())){
			                			map.setFee3(child3.getTextTrim());
			                		}else if("flux1".equals(child3.getName())){
			                			map.setFlux1(child3.getTextTrim());
			                		}else if("flux2".equals(child3.getName())){
			                			map.setFlux2(child3.getTextTrim());
			                		}else if("flux3".equals(child3.getName())){
			                			map.setFlux3(child3.getTextTrim());
			                		}else if("fluxInfo".equals(child3.getName())){
			                			map.setFluxInfo(child3.getTextTrim());
			                		}else if("nextStartInfo".equals(child3.getName())){
			                			map.setNextStartInfo(child3.getTextTrim());
			                		}else if("nextStartRowKey".equals(child3.getName())){
			                			map.setNextStartRowKey(child3.getTextTrim());
			                		}else if("success".equals(child3.getName())){
			                			map.setSuccess(Boolean.valueOf(child3.getTextTrim()));
			                		}else if("totalSize".equals(child3.getName())){
			                			map.setTotalSize(child3.getTextTrim());
			                		}else if("result".equals(child3.getName())){
			                			_log.info("result6666-----" +child3.getTextTrim());
			                			result.add(child3.getTextTrim());
			                		}
								}
							}
						}
                	}
            }  
        }  
        map.setResult(result);
        map.isSuccess();
        return map;  
    } 
    
    
    /**   
     * 将元为单位的转换为分 替换小数点，支持以逗号区分的金额  
     *   
     * @param amount  
     * @return  
     */    
    public static String changeY2F(String amount){    
        String currency =  amount.replaceAll("\\$|\\￥|\\,", "");  //处理包含, ￥ 或者$的金额    
        int index = currency.indexOf(".");    
        int length = currency.length();    
        Long amLong = 0l;    
        if(index == -1){    
            amLong = Long.valueOf(currency+"00");    
        }else if(length - index >= 3){    
            amLong = Long.valueOf((currency.substring(0, index+3)).replace(".", ""));    
        }else if(length - index == 2){    
            amLong = Long.valueOf((currency.substring(0, index+2)).replace(".", "")+0);    
        }else{    
            amLong = Long.valueOf((currency.substring(0, index+1)).replace(".", "")+"00");    
        }    
        return amLong.toString();    
    }   
    
	
}
